import {create} from 'zustand'
import {dataSourceApi} from '@services/api/dataSource'
import type {DataSourceTreeNode} from '@components/business/DataSourceTree/types'
import type {CatalogVo, Column, Database, Dimension, Table} from '@/types/api'

interface DataSourceState {
  // 树与选择
  treeData: DataSourceTreeNode[]
  selectedNode: DataSourceTreeNode | null

  // 列表与详情缓存（可按需填充）
  catalogs: CatalogVo[]
  databases: Database[]
  tables: Table[]
  columns: Column[]
  dimensions: Dimension[]

  // 状态
  loading: boolean
  error: string | null
  displayServer: boolean
  displayTable: boolean

  // 设置
  setDisplayOptions: (options: { displayServer?: boolean; displayTable?: boolean }) => void
  setTreeData: (data: DataSourceTreeNode[]) => void
  setSelectedNode: (node: DataSourceTreeNode | null) => void

  // 异步载入
  loadTree: () => Promise<void>
  loadCatalogs: () => Promise<void>
  loadDatabases: (catalogName: string) => Promise<void>
  loadTables: (catalogName: string, databaseName: string) => Promise<void>
  loadColumns: (catalogName: string, databaseName: string, tableName: string) => Promise<void>
  loadDimensions: (catalogName: string, databaseName: string, tableName: string) => Promise<void>

  // 操作
  testConnection: (catalogName: string, type: 'server' | 'jdbc' | 'doris') => Promise<boolean>
  syncCatalog: (catalogName: string) => Promise<void>
  syncDatabase: (catalogName: string, databaseName: string) => Promise<void>
  setEnabled: (payload: { level: 'catalog' | 'database' | 'table'; catalogName: string; databaseName?: string; tableName?: string; enabled: boolean }) => Promise<void>
  updateSystemCode: (payload: { level: 'catalog' | 'database' | 'table'; catalogName: string; databaseName?: string; tableName?: string; systemCode: string }) => Promise<void>
  generateDorisScript: (catalogName: string, databaseName: string, tableName: string) => Promise<string>
}

export const useDataSourceStore = create<DataSourceState>((set, get) => ({
  // 初始状态
  treeData: [],
  selectedNode: null,
  catalogs: [],
  databases: [],
  tables: [],
  columns: [],
  dimensions: [],
  loading: false,
  error: null,
  displayServer: false,
  displayTable: false,

  // 设置
  setDisplayOptions: (options) => set((state) => ({
    displayServer: options.displayServer ?? state.displayServer,
    displayTable: options.displayTable ?? state.displayTable,
  })),

  setTreeData: (data) => set({ treeData: data }),

  setSelectedNode: (node) => set({ selectedNode: node }),

  // 载入
  loadTree: async () => {
    set({ loading: true, error: null })
    try {
      const { displayServer, displayTable } = get()
      const data = await dataSourceApi.getTree(displayServer, displayTable)
      set({ treeData: data, loading: false })
    } catch (e: any) {
      set({ loading: false, error: e?.message || '加载失败' })
    }
  },

  loadCatalogs: async () => {
    try {
      const catalogs = await dataSourceApi.getCatalogs()
      set({ catalogs })
    } catch (e: any) {
      set({ error: e?.message || '加载目录失败' })
    }
  },

  loadDatabases: async (catalogName) => {
    try {
      const dbs = await dataSourceApi.getDatabases(catalogName)
      set({ databases: dbs })
    } catch (e: any) {
      set({ error: e?.message || '加载数据库失败' })
    }
  },

  loadTables: async (catalogName, databaseName) => {
    try {
      const tbs = await dataSourceApi.getTables(catalogName, databaseName)
      set({ tables: tbs })
    } catch (e: any) {
      set({ error: e?.message || '加载表失败' })
    }
  },

  loadColumns: async (catalogName, databaseName, tableName) => {
    try {
      const cols = await dataSourceApi.getColumns(catalogName, databaseName, tableName)
      set({ columns: cols })
    } catch (e: any) {
      set({ error: e?.message || '加载列失败' })
    }
  },

  loadDimensions: async (catalogName, databaseName, tableName) => {
    try {
      const dims = await dataSourceApi.getDimensions(catalogName, databaseName, tableName)
      set({ dimensions: dims })
    } catch (e: any) {
      set({ error: e?.message || '加载维度失败' })
    }
  },

  // 操作
  testConnection: async (catalogName, type) => {
    switch (type) {
      case 'server':
        return await dataSourceApi.testServer(catalogName)
      case 'jdbc':
        return await dataSourceApi.testJdbc(catalogName)
      case 'doris':
        return await dataSourceApi.testDoris(catalogName)
      default:
        return false
    }
  },

  syncCatalog: async (catalogName) => {
    set({ loading: true })
    await dataSourceApi.syncCatalog(catalogName)
    await get().loadTree()
    set({ loading: false })
  },

  syncDatabase: async (catalogName, databaseName) => {
    set({ loading: true })
    await dataSourceApi.syncDatabase(catalogName, databaseName)
    await get().loadTree()
    set({ loading: false })
  },

  setEnabled: async ({ level, catalogName, databaseName, tableName, enabled }) => {
    switch (level) {
      case 'catalog':
        await dataSourceApi.setCatalogEnabled(catalogName, enabled)
        break
      case 'database':
        if (!databaseName) return
        await dataSourceApi.setDatabaseEnabled(catalogName, databaseName, enabled)
        break
      case 'table':
        if (!databaseName || !tableName) return
        await dataSourceApi.setTableEnabled(catalogName, databaseName, tableName, enabled)
        break
    }
    await get().loadTree()
  },

  updateSystemCode: async ({ level, catalogName, databaseName, tableName, systemCode }) => {
    switch (level) {
      case 'catalog':
        await dataSourceApi.updateCatalogSystemCode(catalogName, systemCode)
        break
      case 'database':
        if (!databaseName) return
        await dataSourceApi.updateDatabaseSystemCode(catalogName, databaseName, systemCode)
        break
      case 'table':
        if (!databaseName || !tableName) return
        await dataSourceApi.updateTableSystemCode(catalogName, databaseName, tableName, systemCode)
        break
    }
    await get().loadTree()
  },

  generateDorisScript: async (catalogName, databaseName, tableName) => {
    return await dataSourceApi.generateDorisScript(catalogName, databaseName, tableName)
  },
}))